package com.ala4.oxcafe.common.utils.collection;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 集合工具类
 *
 * @author PING
 * @version 1.0.0
 * @date 2025/7/31 15:49
 */
public class CollUtil {

    private CollUtil() {
    }

    /**
     * 集合判空
     *
     * @param coll 集合
     * @return
     */
    public static boolean isEmpty(Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }

    /**
     * 集合非空
     * @param coll
     * @return
     */
    public static boolean isNotEmpty(Collection<?> coll) {
        return !isEmpty(coll);
    }

    /**
     * 集合创建
     * @param elements
     * @return
     * @param <T>
     */
    @SafeVarargs
    public static <T> List<T> newArrayList(T... elements) {
        return new ArrayList<>(Arrays.asList(elements));
    }

    @SafeVarargs
    public static <T> Set<T> newHashSet(T... elements) {
        return new HashSet<>(Arrays.asList(elements));
    }

    // ----------------- 集合操作 -----------------

    /**
     * 合并多个集合（不去重）
     *
     * @param collections 待合并的集合
     * @return 合并后的新集合
     */
    @SafeVarargs
    public static <T> List<T> unionAll(Collection<? extends T>... collections) {
        return Arrays.stream(collections)
                .filter(CollUtil::isNotEmpty)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }

    /**
     * 求交集
     *
     * @param coll1 集合1
     * @param coll2 集合2
     * @return 交集结果
     */
    public static <T> List<T> intersection(Collection<T> coll1, Collection<T> coll2) {
        if (isEmpty(coll1) || isEmpty(coll2)) {
            return Collections.emptyList();
        }
        return coll1.stream()
                .filter(coll2::contains)
                .collect(Collectors.toList());
    }

    /**
     * 求差集（coll1 有但 coll2 没有的元素）
     *
     * @param coll1 集合1
     * @param coll2 集合2
     * @return 差集结果
     */
    public static <T> List<T> subtract(Collection<T> coll1, Collection<T> coll2) {
        if (isEmpty(coll1)) {
            return Collections.emptyList();
        }
        if (isEmpty(coll2)) return new ArrayList<>(coll1);
        return coll1.stream()
                .filter(e -> !coll2.contains(e))
                .collect(Collectors.toList());
    }

    /**
     * 去重
     *
     * @param coll 原始集合
     * @return 去重后的新集合
     */
    public static <T> List<T> distinct(Collection<T> coll) {
        return isEmpty(coll)
                ? Collections.emptyList()
                : coll.stream().distinct().collect(Collectors.toList());
    }

    // ----------------- 集合转换 -----------------

    /**
     * 将集合连接为字符串
     *
     * @param coll      集合
     * @param separator 分隔符
     * @return 连接后的字符串
     */
    public static String join(Collection<?> coll, String separator) {
        if (isEmpty(coll)) {
            return "";
        }
        return coll.stream()
                .map(Object::toString)
                .collect(Collectors.joining(separator));
    }

    /**
     * 将集合转换为Map
     *
     * @param coll        数据集合
     * @param keyMapper   生成Key的函数
     * @param valueMapper 生成Value的函数
     * @return 转换后的Map
     */
    public static <K, V, T> Map<K, V> toMap(
            Collection<T> coll,
            Function<T, K> keyMapper,
            Function<T, V> valueMapper
    ) {
        return isEmpty(coll)
                ? Collections.emptyMap()
                : coll.stream().collect(Collectors.toMap(keyMapper, valueMapper));
    }

    // ----------------- 集合过滤 -----------------

    /**
     * 过滤集合元素
     *
     * @param coll      原始集合
     * @param predicate 过滤条件
     * @return 过滤后的新集合
     */
    public static <T> List<T> filter(Collection<T> coll, Predicate<T> predicate) {
        return isEmpty(coll)
                ? Collections.emptyList()
                : coll.stream().filter(predicate).collect(Collectors.toList());
    }

    // ----------------- 其他工具 -----------------

    /**
     * 分页截取集合
     *
     * @param coll     原始集合
     * @param pageNum  页码（从1开始）
     * @param pageSize 每页数量
     * @return 分页后的子集合
     */
    public static <T> List<T> page(Collection<T> coll, int pageNum, int pageSize) {
        if (isEmpty(coll)) {
            return Collections.emptyList();
        }
        int start = (pageNum - 1) * pageSize;
        if (start >= coll.size()) {
            return Collections.emptyList();
        }
        int end = Math.min(start + pageSize, coll.size());
        return new ArrayList<>(coll).subList(start, end);
    }

}
